{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Load adapters with 🤗 PEFT"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Parameter-Efficient Fine Tuning (PEFT)](https://huggingface.co/blog/peft) メソッドは、事前学習済みモデルのパラメータをファインチューニング中に凍結し、その上にわずかな訓練可能なパラメータ（アダプター）を追加するアプローチです。アダプターは、タスク固有の情報を学習するために訓練されます。このアプローチは、メモリ使用量が少なく、完全にファインチューニングされたモデルと比較して計算リソースを低く抑えつつ、同等の結果を生成することが示されています。\n",
    "\n",
    "PEFTで訓練されたアダプターは通常、完全なモデルのサイズよりも1桁小さく、共有、保存、読み込むのが便利です。\n",
    "\n",
    "<div class=\"flex flex-col justify-center\">\n",
    "  <img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/peft/PEFT-hub-screenshot.png\"/>\n",
    "  <figcaption class=\"text-center\">Hubに格納されているOPTForCausalLMモデルのアダプター重みは、モデルの全体サイズの約6MBで、モデル重みの全サイズは約700MBです。</figcaption>\n",
    "</div>\n",
    "\n",
    "🤗 PEFTライブラリについて詳しく知りたい場合は、[ドキュメンテーション](https://huggingface.co/docs/peft/index)をご覧ください。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "🤗 PEFTをインストールして始めましょう：\n",
    "\n",
    "\n",
    "```bash\n",
    "pip install peft\n",
    "```\n",
    "\n",
    "新機能を試してみたい場合、ソースからライブラリをインストールすることに興味があるかもしれません：\n",
    "\n",
    "```bash\n",
    "pip install git+https://github.com/huggingface/peft.git\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Supported PEFT models"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "🤗 Transformersは、いくつかのPEFT（Parameter Efficient Fine-Tuning）メソッドをネイティブにサポートしており、ローカルまたはHubに格納されたアダプターウェイトを簡単に読み込んで実行またはトレーニングできます。以下のメソッドがサポートされています：\n",
    "\n",
    "- [Low Rank Adapters](https://huggingface.co/docs/peft/conceptual_guides/lora)\n",
    "- [IA3](https://huggingface.co/docs/peft/conceptual_guides/ia3)\n",
    "- [AdaLoRA](https://huggingface.co/papers/2303.10512)\n",
    "\n",
    "他のPEFTメソッドを使用したい場合、プロンプト学習やプロンプト調整などについて詳しく知りたい場合、または🤗 PEFTライブラリ全般については、[ドキュメンテーション](https://huggingface.co/docs/peft/index)を参照してください。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load a PEFT adapter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "🤗 TransformersからPEFTアダプターモデルを読み込んで使用するには、Hubリポジトリまたはローカルディレクトリに `adapter_config.json` ファイルとアダプターウェイトが含まれていることを確認してください。次に、`AutoModelFor` クラスを使用してPEFTアダプターモデルを読み込むことができます。たとえば、因果言語モデリング用のPEFTアダプターモデルを読み込むには：\n",
    "\n",
    "1. PEFTモデルのIDを指定します。\n",
    "2. それを[AutoModelForCausalLM](https://huggingface.co/docs/transformers/main/ja/model_doc/auto#transformers.AutoModelForCausalLM) クラスに渡します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoModelForCausalLM, AutoTokenizer\n",
    "\n",
    "peft_model_id = \"ybelkada/opt-350m-lora\"\n",
    "model = AutoModelForCausalLM.from_pretrained(peft_model_id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<Tip>\n",
    "\n",
    "PEFTアダプターを`AutoModelFor`クラスまたは基本モデルクラス（`OPTForCausalLM`または`LlamaForCausalLM`など）で読み込むことができます。\n",
    "\n",
    "</Tip>\n",
    "\n",
    "また、`load_adapter`メソッドを呼び出すことで、PEFTアダプターを読み込むこともできます："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoModelForCausalLM, AutoTokenizer\n",
    "\n",
    "model_id = \"facebook/opt-350m\"\n",
    "peft_model_id = \"ybelkada/opt-350m-lora\"\n",
    "\n",
    "model = AutoModelForCausalLM.from_pretrained(model_id)\n",
    "model.load_adapter(peft_model_id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load in 8bit or 4bit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`bitsandbytes` 統合は、8ビットおよび4ビットの精度データ型をサポートしており、大規模なモデルを読み込む際にメモリを節約するのに役立ちます（詳細については `bitsandbytes` 統合の[ガイド](https://huggingface.co/docs/transformers/main/ja/./quantization#bitsandbytes-integration)を参照してください）。[from_pretrained()](https://huggingface.co/docs/transformers/main/ja/main_classes/model#transformers.PreTrainedModel.from_pretrained) に `load_in_8bit` または `load_in_4bit` パラメータを追加し、`device_map=\"auto\"` を設定してモデルを効果的にハードウェアに分散配置できます："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig\n",
    "\n",
    "peft_model_id = \"ybelkada/opt-350m-lora\"\n",
    "model = AutoModelForCausalLM.from_pretrained(peft_model_id, quantization_config=BitsAndBytesConfig(load_in_8bit=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Add a new adapter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "既存のアダプターを持つモデルに新しいアダプターを追加するために `add_adapter` を使用できます。ただし、新しいアダプターは現在のアダプターと同じタイプである限り、これを行うことができます。たとえば、モデルに既存の LoRA アダプターがアタッチされている場合："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer\n",
    "from peft import PeftConfig\n",
    "\n",
    "model_id = \"facebook/opt-350m\"\n",
    "model = AutoModelForCausalLM.from_pretrained(model_id)\n",
    "\n",
    "lora_config = LoraConfig(\n",
    "    target_modules=[\"q_proj\", \"k_proj\"],\n",
    "    init_lora_weights=False\n",
    ")\n",
    "\n",
    "model.add_adapter(lora_config, adapter_name=\"adapter_1\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "新しいアダプタを追加するには:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# attach new adapter with same config\n",
    "model.add_adapter(lora_config, adapter_name=\"adapter_2\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`set_adapter` を使用して、どのアダプターを使用するかを設定できます："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# use adapter_1\n",
    "model.set_adapter(\"adapter_1\")\n",
    "output = model.generate(**inputs)\n",
    "print(tokenizer.decode(output_disabled[0], skip_special_tokens=True))\n",
    "\n",
    "# use adapter_2\n",
    "model.set_adapter(\"adapter_2\")\n",
    "output_enabled = model.generate(**inputs)\n",
    "print(tokenizer.decode(output_enabled[0], skip_special_tokens=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Enable and disable adapters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "モデルにアダプターを追加したら、アダプターモジュールを有効または無効にすることができます。アダプターモジュールを有効にするには、次の手順を実行します："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer\n",
    "from peft import PeftConfig\n",
    "\n",
    "model_id = \"facebook/opt-350m\"\n",
    "adapter_model_id = \"ybelkada/opt-350m-lora\"\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
    "text = \"Hello\"\n",
    "inputs = tokenizer(text, return_tensors=\"pt\")\n",
    "\n",
    "model = AutoModelForCausalLM.from_pretrained(model_id)\n",
    "peft_config = PeftConfig.from_pretrained(adapter_model_id)\n",
    "\n",
    "# to initiate with random weights\n",
    "peft_config.init_lora_weights = False\n",
    "\n",
    "model.add_adapter(peft_config)\n",
    "model.enable_adapters()\n",
    "output = model.generate(**inputs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "アダプターモジュールを無効にするには："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.disable_adapters()\n",
    "output = model.generate(**inputs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train a PEFT adapter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "PEFTアダプターは[Trainer](https://huggingface.co/docs/transformers/main/ja/main_classes/trainer#transformers.Trainer)クラスでサポートされており、特定のユースケースに対してアダプターをトレーニングすることができます。数行のコードを追加するだけで済みます。たとえば、LoRAアダプターをトレーニングする場合:\n",
    "\n",
    "<Tip>\n",
    "\n",
    "[Trainer](https://huggingface.co/docs/transformers/main/ja/main_classes/trainer#transformers.Trainer)を使用したモデルの微調整に慣れていない場合は、[事前トレーニング済みモデルの微調整](https://huggingface.co/docs/transformers/main/ja/training)チュートリアルをご覧ください。\n",
    "\n",
    "</Tip>\n",
    "\n",
    "1. タスクタイプとハイパーパラメータに対するアダプターの構成を定義します（ハイパーパラメータの詳細については`LoraConfig`を参照してください）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from peft import LoraConfig\n",
    "\n",
    "peft_config = LoraConfig(\n",
    "    lora_alpha=16,\n",
    "    lora_dropout=0.1,\n",
    "    r=64,\n",
    "    bias=\"none\",\n",
    "    task_type=\"CAUSAL_LM\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. モデルにアダプターを追加する。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.add_adapter(peft_config)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. これで、モデルを [Trainer](https://huggingface.co/docs/transformers/main/ja/main_classes/trainer#transformers.Trainer) に渡すことができます！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "trainer = Trainer(model=model, ...)\n",
    "trainer.train()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "保存するトレーニング済みアダプタとそれを読み込むための手順："
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 4
}
